#ifndef LEXER_H
#define LEXER_H

#include <string_view>
#include <string>
#include <memory>

enum class TokenKind
{
    Plus,
    Minus,
    Star,
    Slash,
    Eof,
    Num,
    LParent,
    RParent,
    LBacket,
    RBacket,
    LBrace,
    RBrace,
    Identifier, // 标识符
    Semicolon,  // 分号
    Assign,     // 等号赋值
    Equal,      // 连等，判断相等
    PipeEqual,
    Greater,
    GreaterEqual,
    Lesser,
    LesserEqual,
    If,
    Else,
    While,
    For,
    Comma, // 逗号
    Return,
    Char,       // char类型声明
    Short,      // short类型声明
    Int,        // int类型声明
    Long,       // long类型声明
    Amp,        // 取地址符&
    Sizeof,
};

struct SourceCodeLocation
{
    int Line;
    int Col;
};

class Token
{
public:
    TokenKind Kind;
    SourceCodeLocation Location;
    int Value;
    std::string_view Content;
};

class Lexer
{
public:
    std::shared_ptr<Token> CurrentToken;
    std::string_view SourceCode;

    char CurrentChar = ' ';
    int NextCharIdx = 0; // 当前字符下一个字符的下标
    int Line = 0;
    int LineHead = 0;

    char SavePointChar = ' ';
    int SavePointNextCharIdx = 0;
    int SavePointLine = 0;
    int SavePointLineHead = 0;
    std::shared_ptr<Token> SavePointToken;

    Lexer(const char *code)
    {
        SourceCode = code;
    }

    void GetNextToken();
    void GetNextChar();
    void PrintAllToken();
    void ExceptToken(TokenKind kind);

    void SaveStatus();
    void LoadStatus();

private:
    void SkipWhiteSpace();
    void SkipComment();

    bool IsLetter();
    bool IsDigit();
    bool IsLetterOrDigit();
    const char *GetTokenKindSpellint(TokenKind kind);
    char PeekChar(int distance);
};

#endif // !LEXER_H